import { animation, Animation, AnimationClip, Node, Size, Sprite, SpriteFrame, UITransform } from 'cc';
import { loadSpriteFrameDir } from './resources';

type AnimaConfig = {
    name: string; // clip名称
    loop?: boolean; // 是否循环播放
    interval?: number; // 帧间隔
    size?: Size;
};

export class AnimationTools {
    static #instance: AnimationTools;
    public static get instance(): AnimationTools {
        if (!this.#instance) this.#instance = new AnimationTools();
        return this.#instance;
    }
    private constructor() {}

    public async addAnimationClip(node: Node, src: string | Array<SpriteFrame>, config: AnimaConfig): Promise<AnimationClip> {
        const anima = this.checkAnimationComponent(node);
        let spriteFrames: SpriteFrame[];
        if (typeof src === 'string') {
            spriteFrames = await loadSpriteFrameDir(src);
        } else {
            spriteFrames = src;
        }
        if (spriteFrames.length !== 0) {
            const size = config.size || new Size(spriteFrames[0].width, spriteFrames[0].height);
            node.getComponent(UITransform).setContentSize(size);
        }
        let totalFrame = spriteFrames.length;
        const frames: Array<[number, SpriteFrame]> = spriteFrames.map((item: SpriteFrame, index) => {
            return [index / totalFrame, item];
        });

        const track = new animation.ObjectTrack();
        track.path = new animation.TrackPath().toComponent(Sprite).toProperty('spriteFrame');
        track.channel.curve.assignSorted(frames);

        const animationClip = new AnimationClip();
        animationClip.addTrack(track);
        animationClip.duration = ((config.interval | 5) * totalFrame) / 25;
        if (config.loop) animationClip.wrapMode = AnimationClip.WrapMode.Loop;
        anima.addClip(animationClip, config.name);
        anima.play(config.name);
        return animationClip;
    }
    private checkAnimationComponent(node: Node): Animation {
        let sprite = node.getComponent(Sprite);
        if (!sprite) sprite = node.addComponent(Sprite);
        sprite.sizeMode = Sprite.SizeMode.CUSTOM;

        let anima = node.getComponent(Animation);
        if (!anima) anima = node.addComponent(Animation);
        return anima;
    }
}
